﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Windows;
using InnovTech.Util;

namespace InnovTech.Wpf
{
    public static class WpfWeakActionExt
    {
        private static WeakRefCollection _refCollection = new WeakRefCollection(20);
        private static IEnumerable<WeakAction> WeakActions
        {
            get
            {
                return _refCollection.OfType<WeakAction>();
            }
        }

        /// <summary>
        /// Cleans up the actions that are not alive anymore.
        /// </summary>
        public static void CleanupLocalizationActions()
        {
            _refCollection.CleanUp();
        }

        /// <summary>
        /// Invokes all actions that are managed by the central collection and still alive.
        /// </summary>
        public static void ExecuteActions()
        {
            _refCollection.CleanUp();
            WeakActions.ToList().ForEach(wa =>
                {
                    wa.Invoke();
                });
        }

        #region Extension methods of FrameworkElement
        public static void RegisterWeakAction(this FrameworkElement target, Action localizationInfo)
        {

            Expression<Action> expr = () => localizationInfo();

            WeakAction act = new WeakAction(target, expr);

            target.Loaded += (sender, args) =>
            {
                CreateWeakActionAndInvoke(target, expr);
            };

            if (target.IsLoaded)
            {
                CreateWeakActionAndInvoke(target, expr);
            }
            
            target.Unloaded += (sender, args) =>
            {
                UnregisterWeakAction(target);
            };
        }

        /// <summary>
        /// Forces to remove the Action which belongs to the given target object.
        /// </summary>
        /// <param name="target"></param>
        public static void UnregisterWeakAction(this FrameworkElement target)
        {
            WeakAction wa = _refCollection.OfType<WeakAction>().SingleOrDefault(action =>
            {
                return action.Target == target;
            });

            if (wa != null)
                _refCollection.Remove(wa);
        }
        

        private static void CreateWeakActionAndInvoke(object target, Expression<Action> updateAction)
        {
            var act = CreateWeakAction(target, updateAction);
            act.Invoke();
        }

        private static WeakAction CreateWeakAction(object target, Expression<Action> updateAction)
        {
            var act = new WeakAction(target, updateAction);
            _refCollection.Add(act);
            return act;
        }

        #endregion Extension methods of FrameworkElement


    }
}
